package com.zlq.cn.service.ai;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.volcengine.service.visual.IVisualService;
import com.volcengine.service.visual.model.request.*;
import com.volcengine.service.visual.model.response.*;
import com.zlq.cn.config.Config;
import com.zlq.cn.config.FinderConfiguration;
import com.zlq.cn.dto.visual.request.AllAgeGenerationRequest;
import com.zlq.cn.dto.visual.request.DollyZoomRequest;
import com.zlq.cn.dto.visual.response.AllAgeGenerationResponse;
import com.zlq.cn.dto.visual.response.DollyZoomResponse;
import com.zlq.cn.entity.TencentAi;
import com.zlq.cn.mapper.ai.TencentAiMapper;
import com.zlq.cn.service.un.ConfigService;
import lombok.SneakyThrows;
import one.util.streamex.StreamEx;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * @author zhoucl
 * @date 2023年04月03日 14:23
 */
@Service("volcengineService")
public class VolcengineService extends ServiceImpl<TencentAiMapper, TencentAi> {

    private final ConfigService configService;

    private final MyVisualService myVisualService;

    private final IVisualService visualService;

    private final AiCommonService aiCommonService;

    public VolcengineService(AiCommonService aiCommonService,
                             ConfigService configService,
                             FinderConfiguration configuration,
                             MyVisualService myVisualService) {
        this.aiCommonService = aiCommonService;
        this.configService = configService;
        this.myVisualService = myVisualService;

        visualService = myVisualService.visualService;
    }

    @SneakyThrows
    public VisualImageFlowResponse imageFlow(VisualImageFlowRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualImageFlowResponse rep = visualService.imageFlow(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        byte[] decode = Base64.decode(rep.getData().getVideo());
        rep.getData().setVideo(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "imageFlow", beforeImage,
                configService.putObject("volcengine/imageFlow", beforeImage, ".mp4", decode)));
        return rep;
    }

    @SneakyThrows
    public VisualImageScoreResponse imageScore(VisualImageScoreRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualImageScoreResponse rep = visualService.imageScore(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "imageScore", beforeImage, JSON.toJSONString(rep.getData()));
        return rep;
    }

    @SneakyThrows
    public VisualPoemMaterialResponse poemMaterial(VisualPoemMaterialRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualPoemMaterialResponse rep = visualService.poemMaterial(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "poemMaterial", beforeImage, JSON.toJSONString(rep.getData()));
        return rep;
    }

    @SneakyThrows
    public VisualFaceSwapResponse faceSwap(VisualFaceSwapRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        req.setTemplateBase64(configService.toBase64(req.getTemplateBase64()));
        VisualFaceSwapResponse rep = visualService.faceSwap(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        byte[] decode = Base64.decode(rep.getData().getImage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "faceSwap", beforeImage,
                configService.putObject("volcengine/faceSwap", beforeImage, null, decode)));
        return rep;
    }

    @SneakyThrows
    public VisualJPCartoonResponse jpCartoon(VisualJPCartoonRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualJPCartoonResponse rep = visualService.jpCartoon(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        StringJoiner sj = new StringJoiner(",");
        if (StringUtils.isNotEmpty(rep.getData().getImage())) {
            String volcengine = configService.putObject("volcengine/jpCartoon", beforeImage, null, Base64.decode(rep.getData().getImage()));
            rep.getData().setImage(volcengine);
            sj.add(volcengine);
        }
        String clip = rep.getData().getClip();
        if (StringUtils.isNotEmpty(clip)) {
            String beforeClip = FilenameUtils.getFullPath(beforeImage) + FilenameUtils.getBaseName(beforeImage) + "_head." + FilenameUtils.getExtension(beforeImage);
            String volcengine = configService.putObject("volcengine/jpCartoon", beforeClip, null, Base64.decode(clip));
            rep.getData().setClip(volcengine);
            sj.add(volcengine);
        }
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "jpCartoon", beforeImage, sj.toString());
        return rep;
    }

    @SneakyThrows
    public VisualHumanSegmentResponse humanSegment(VisualHumanSegmentRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualHumanSegmentResponse rep = visualService.humanSegment(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        StringJoiner sj = new StringJoiner(",");
        if (StringUtils.isNotEmpty(rep.getData().getImage())) {
            String volcengine = configService.putObject("volcenginehumanSegment/", beforeImage, null, Base64.decode(rep.getData().getImage()));
            rep.getData().setImage(volcengine);
            sj.add(volcengine);
        }
        String foreGroundImage = rep.getData().getForeGroundImage();
        if (StringUtils.isNotEmpty(foreGroundImage)) {
            String beforeClip = FilenameUtils.getFullPath(beforeImage) + FilenameUtils.getBaseName(beforeImage) + "_foreground." + FilenameUtils.getExtension(beforeImage);
            String volcengine = configService.putObject("volcengine/humanSegment", beforeClip, null, Base64.decode(foreGroundImage));
            rep.getData().setForeGroundImage(volcengine);
            sj.add(volcengine);
        }
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "humanSegment", beforeImage, sj.toString());
        return rep;
    }

    @SneakyThrows
    public VisualEyeClose2OpenResponse eyeClose2Open(VisualEyeClose2OpenRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualEyeClose2OpenResponse rep = visualService.eyeClose2Open(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "eyeClose2Open", beforeImage,
                configService.putObject("volcengine/eyeClose2Open", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualEmoticonEditResponse emotionEdit(VisualEmoticonEditRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualEmoticonEditResponse rep = visualService.emotionEdit(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "emotionEdit", beforeImage,
                configService.putObject("volcengine/emotionEdit", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualDistortionFreeResponse distortionFree(VisualDistortionFreeRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualDistortionFreeResponse rep = visualService.distortionFree(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "distortionFree", beforeImage,
                configService.putObject("volcengine/distortionFree", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualStretchRecoveryResponse stretchRecovery(VisualStretchRecoveryRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualStretchRecoveryResponse rep = visualService.stretchRecovery(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "stretchRecovery", beforeImage,
                configService.putObject("volcengine/stretchRecovery", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualEnhancePhotoResponse enhancePhoto(VisualEnhancePhotoRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualEnhancePhotoResponse rep = visualService.enhancePhoto(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "enhancePhoto", beforeImage,
                configService.putObject("volcengine/enhancePhoto", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualConvertPhotoResponse convertPhoto(VisualConvertPhotoRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        VisualConvertPhotoResponse rep = visualService.convertPhoto(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImage(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "convertPhoto", beforeImage,
                configService.putObject("volcengine/convertPhoto", beforeImage, null, Base64.decode(rep.getData().getImage()))));
        return rep;
    }

    @SneakyThrows
    public VisualPotraitEffectResponse potraitEffect(VisualPotraitEffectRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        VisualPotraitEffectResponse rep = visualService.potraitEffect(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        rep.getData().setImageUrl(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "potraitEffect", req.getImageUrl(),
                configService.putObject("volcengine/potraitEffect", rep.getData().getImageUrl())));
        return rep;
    }

    @SneakyThrows
    public DollyZoomResponse dollyZoom(DollyZoomRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        String beforeImage = req.getImageBase64();
        req.setImageBase64(configService.toBase64(beforeImage));
        DollyZoomResponse rep = myVisualService.dollyZoom(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        byte[] decode = Base64.decode(rep.getData().getVideo());
        rep.getData().setVideo(aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "dollyZoom", beforeImage,
                configService.putObject("volcengine/dollyZoom", beforeImage, ".mp4", decode)));
        return rep;
    }

    @SneakyThrows
    public VisualImg2Video3DResponse img2Video3D(VisualImg2Video3DRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        ArrayList<String> binaryDataBase64 = req.getBinaryDataBase64();
        Assert.notEmpty(binaryDataBase64, "请传递图片");
        List<String> strings = StreamEx.of(binaryDataBase64)
                .map(configService::toBase64)
                .collect(Collectors.toList());
        req.setBinaryDataBase64(new ArrayList<>(strings));
        VisualImg2Video3DResponse rep = visualService.img2Video3D(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        VisualImg2Video3DResponse.Img2Video3DData.AlgorithmBaseResp algorithmBaseResp = rep.getData().getAlgorithmBaseResp();
        Assert.state(algorithmBaseResp.getStatusCode() == 0, rep.getMessage());
        ArrayList<String> repImage = rep.getData().getBinaryDataBase64();
        ArrayList<String> retRepImage = new ArrayList<>();
        for (int i = 0; i < repImage.size(); i++) {
            retRepImage.add(configService.putObject("volcengine/img2Video3D", binaryDataBase64.get(i), ".mp4", Base64.decode(repImage.get(i))));
        }
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "img2Video3D",
                JSON.toJSONString(binaryDataBase64), JSON.toJSONString(retRepImage));
        rep.getData().setBinaryDataBase64(retRepImage);
        return rep;
    }

    @SneakyThrows
    public AllAgeGenerationResponse allAgeGeneration(AllAgeGenerationRequest req) {
        aiCommonService.checkUserNum(Config.PROJECT_VOLCENGINE_AI);
        ArrayList<String> binaryDataBase64 = req.getBinaryDataBase64();
        Assert.notEmpty(binaryDataBase64, "请传递图片");
        List<String> strings = StreamEx.of(binaryDataBase64)
                .map(configService::toBase64)
                .collect(Collectors.toList());
        req.setBinaryDataBase64(new ArrayList<>(strings));
        AllAgeGenerationResponse rep = myVisualService.allAgeGeneration(req);
        Assert.state(rep.getCode() == 10000, rep.getMessage());
        AllAgeGenerationResponse.AllAgeGenerationData.AlgorithmBaseResp algorithmBaseResp = rep.getData().getAlgorithmBaseResp();
        Assert.state(algorithmBaseResp.getStatusCode() == 0, rep.getMessage());
        ArrayList<String> repImage = rep.getData().getBinaryDataBase64();
        ArrayList<String> retRepImage = new ArrayList<>();
        for (int i = 0; i < repImage.size(); i++) {
            retRepImage.add(configService.putObject("volcengine/allAgeGeneration", binaryDataBase64.get(i), null, Base64.decode(repImage.get(i))));
        }
        aiCommonService.saveTencentAi(Config.PROJECT_VOLCENGINE_AI, "allAgeGeneration",
                JSON.toJSONString(binaryDataBase64), JSON.toJSONString(retRepImage));
        rep.getData().setBinaryDataBase64(retRepImage);
        return rep;
    }
}
